﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Magnet.Engine;
namespace Magnet.Engine.Entites
{
    public class Player : Magnet
    {
        public enum PlayerState
        {
            SlowMotion, Spawning, Normal, Dieing, Moving
        }
        //Frame animation
        protected int resetFrame;
        protected int startFrame;
        protected int stopFrame;
        protected int frameCount = 1;
        protected int frameRow = 0;
        protected float FPS;
        protected float totalElapsed;
        protected bool isAnimating;
        protected bool isShowing = true;
        protected bool loop = true;
        protected int loopCounter = 0;

        //flicker
        const float FLICKER_FREQUENCY = 10f;
        protected bool visible;
        protected bool flicker;
        protected double nextFlickerUpdate;

        //scale
        protected float scale = 1.0f;
        protected float scaleTime;
        protected float scalePerSecond;

        PlayerState playerState;

        #region Properties
        public bool IsShowing
        {
            get { return this.isShowing; }
            set { this.isShowing = value; }
        }
        public bool IsAnimating
        {
            get { return this.isAnimating; }
            set { this.isAnimating = value; }
        }
        public bool Loop
        {
            get { return this.loop; }
            set { this.loop = value; }
        }
        public int LoopCounter
        {
            get { return this.loopCounter; }
            set { this.loopCounter = value; }
        }
        public bool Flicker
        {
            set
            {
                this.flicker = value;
                this.visible = !value;
            }
        }
        public float Scale
        {
            get { return this.scale; }
            set { this.scale = value; }
        }
        public bool IsScaling
        {
            get { return this.scaleTime > 0f; }
        }
        #endregion

        public Player(Vector2 position, Vector2 size, String texture) 
            : base(position, size, texture)
        {
            //this.playerState = PlayerState.Normal;
        }

        public PlayerState PlayerStates
        {
            set { this.playerState = value; }
        }
        #region update and draw
        public override void Update(float delta)
        {

            float elapsed = delta;
            int total = (int)delta;

            if (this.isAnimating)
            {
                this.totalElapsed += elapsed;
                if (this.totalElapsed > this.FPS)
                {
                    this.startFrame++;
                    // Keep the Frame between 0 and the total frames, minus one.
                    this.startFrame %= this.stopFrame;

                    if (this.startFrame <= resetFrame)
                    {
                        this.startFrame = resetFrame;
                    }

                    this.totalElapsed -= this.FPS;

                    if (!loop)
                    {
                        loopCounter++;
                        if (loopCounter == stopFrame - 1)
                        {
                            this.startFrame = this.stopFrame;
                            loopCounter = stopFrame - 1;
                            isAnimating = false;
                            isShowing = false;
                        }
                    }
                }
            }

            if (this.flicker)
            {
                if (total > nextFlickerUpdate)
                {
                    this.visible = !this.visible;
                    this.nextFlickerUpdate = total + 1 / FLICKER_FREQUENCY;
                }
            }

            if (this.IsScaling)
            {
                this.scale += this.scalePerSecond * elapsed;
                this.scaleTime -= elapsed;
            }
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            Rectangle stop = new Rectangle(((int)this.size.X * this.stopFrame), (int)this.size.Y * this.frameRow, (int)this.size.X, (int)this.size.Y);

            if (this.isAnimating && isShowing)
            {
                if (this.startFrame < this.stopFrame)
                {
                    Rectangle start = new Rectangle(((int)this.size.X * this.startFrame), (int)this.size.Y * this.frameRow, (int)this.size.X, (int)this.size.Y);
                    spriteBatch.Draw(this.texture, this.position, start, this.tint, this.rotation, this.Origin, this.scale, spriteEffect, this.depth);
                }
            }
            if (!this.isAnimating && isShowing)
            {
                spriteBatch.Draw(this.texture, this.position, stop, this.tint, this.rotation, this.origin, this.scale, spriteEffect, this.depth);
            }
        }
        #endregion

        #region animation
        public void setAnimationSequence()
        {
            switch (this.playerState)
            {
                case PlayerState.Dieing:
                    this.isAnimating = true;
                    this.resetFrame = 2;
                    this.startFrame = 2;
                    this.stopFrame = 4;
                    this.frameCount = 2;
                    break;
                case PlayerState.Moving:
                    this.isAnimating = true;
                    this.startFrame = 0;
                    this.stopFrame = 2;
                    this.frameCount = 2;
                    break;
                case PlayerState.Normal:
                    this.stopFrame = 4;
                    break;
                case PlayerState.SlowMotion:
                    break;
                case PlayerState.Spawning:
                    this.stopFrame = 4;
                    break;
            }
        }

        public void StartScale(float targetScale, float scaleTime)
        {
            if (this.IsScaling)
                return;

            this.scaleTime = scaleTime;
            this.scalePerSecond = (targetScale - this.scale) / scaleTime;
        }

        public void StartAnimation(int FPS, PlayerState playerState ,bool loop)
        {
            this.playerState = playerState;
            setAnimationSequence();
            this.FPS = (float)1 / FPS;
            this.loop = loop;
            
        }

        //stop animation of the frame requested. Doesn't hide the actor
        public void StopAnimation(int stopFrame)
        {
            this.isAnimating = false;
            this.stopFrame = stopFrame;
        }
        #endregion
    }
}


